Option Explicit

'################################################################
' Discriptor
' 聚合函数计算列
' 最小值计算列
'################################################################

Implements IDFFilterAggCol
Implements IDFFilterCol

'################################################################
' Field
'################################################################
'------------------------------------
' IDFFilterCol 接口需要使用的数据
'------------------------------------
' 原始列，可以是真实列 DFFilterSingleCol 或者其他包装类型
Private originCol As IDFFilterCol

' 当前列的别名
' 需要手动设置
Private fieldAliasName As String

'------------------------------------
' IDFFilterAggCol 接口需要使用的数据
'------------------------------------
' 当前数聚合列使用的数据源列
Private dataSource As IDFSeries

' 活动行索引
' 只在计算组合式聚合列的结果时使用
Private activeRowIndex As Long

'################################################################
' Constructor
'################################################################
Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
End Sub

'################################################################
' Init
'################################################################
' @param col 原始列对象
' @param val 计算参数，必须是字符串
Public Sub Init(ByRef col As IDFFilterCol)
    ' 1. 参数检测
    ' 1.1 col 必须不能为 Nothing
    If col Is Nothing Then
        Err.Raise 10001, Description:="parameter col must be not nothing"
        Exit Sub
    End If

    ' 1.2 col 不能是聚合列(一个聚合列不能嵌套在另一个聚合列内部)
    If col.isAggregateCol Then
        Err.Raise 10313, Description:="Aggregate Column Parameter [col] can not be nested in other aggregate Column"
        Exit Sub
    End If

    ' 2. 保存基础参数
    Set originCol = col
End Sub

'################################################################
' Property
'################################################################
' 返回列名
' 如果当前列是多个列组合成的或是计算列，则返回 ""
Public Property Get IDFFilterCol_Name() As String
    ' 因为当前列是计算列，所以默认返回 ""
    IDFFilterCol_Name = ""
End Property

' 返回别名
' 如果当前列是多个列组合成的或是计算列（没有手动设置别名的），则返回 ""
Public Property Get IDFFilterCol_AliasName() As String
    IDFFilterCol_AliasName = fieldAliasName
End Property

' 返回别名
' 如果当前列是多个 DFFilter 中的列组合成的，返回 Nothing
Public Property Get IDFFilterCol_Filter() As DFFilter
    Set IDFFilterCol_Filter = originCol.Filter
End Property

' 返回当前列的类型
Public Property Get IDFFilterCol_ColType() As DF_DataType
    ' 固定返回字符串类型
    IDFFilterCol_ColType = originCol.ColType
End Property

' 返回当前列的类型处理器
Public Property Get IDFFilterCol_ColTypeHandle() As IDFDataTypeHandler
    Set IDFFilterCol_ColTypeHandle = originCol.ColTypeHandle
End Property

'################################################################
' IDFFilterAggCol Function
'################################################################
' 设置当前聚合列的数据源
Public Sub IDFFilterAggCol_setDataSource(ByRef ds As IDFSeries)
    Set dataSource = ds
End Sub

' 分段式计算: 筛选过程中的计算
'
' 传入 groupby key 所对应的行索引，然后由聚合列自己去获取上一次的计算结果
' 在聚合列完成当前这一行的计算后，和上一次的结果进行聚合
' @param groupIndex 当前分组所对应的行索引
Public Function IDFFilterAggCol_compute(ByRef groupRowIndex As Long) As Variant
    ' 1. 获取当前这一次的结果
    Dim curResult As Variant
    curResult = originCol.unsafeGetActiveRowVal

    ' 2. 获取上一次的结果
    Dim lastResult As Variant
    lastResult = dataSource.getData(groupRowIndex)

    ' 3. 如果是第一次进入当前的分组，则不进行计算，直接返回当前这一次的结果
    '    否则返回比较之后的结果
    If IsEmpty(lastResult) Then
        IDFFilterAggCol_compute = curResult
    Else
        If curResult < lastResult Then
            IDFFilterAggCol_compute = curResult
        Else
            IDFFilterAggCol_compute = lastResult
        End If
    End If
End Function

' 分段式计算: 是否需要执行筛选结束阶段的计算
Public Function IDFFilterAggCol_hasEndStageCompute() As Boolean
    IDFFilterAggCol_hasEndStageCompute = False
End Function

' 分段式计算: 执行筛选结束阶段的计算
' 传入每个 groupby 的数量，在聚合列内部，完成剩余的计算
' 计算后的结果直接写回数据源对应的槽位上
Public Sub IDFFilterAggCol_executeEndStageComputeByCount(ByRef groubyCountSeries As IDFSeries)
    ' noop
End Sub

' 分段式计算: 组合式聚合列计算最终结果时使用
' 设置当前聚合列的活动行索引
Public Sub IDFFilterAggCol_unsafeSetActiveRowIndex(ByRef rindex As Long)
    activeRowIndex = rindex
End Sub

'################################################################
' IDFFilterCol Function
'################################################################

' ------------------------------------------------------
' 列操作
' ------------------------------------------------------
' 获取当前列中使用的所有真实列对象
' @return HashSet<DFFilterSingleCol>
Public Function IDFFilterCol_getRealUsedCol() As ISet
    Set IDFFilterCol_getRealUsedCol = originCol.getRealUsedCol
End Function

' 获取当前列中使用的所有 Filter
' @return HashSet<DFFilter>
Public Function IDFFilterCol_getAllFilters() As ISet
    Set IDFFilterCol_getAllFilters = originCol.getAllFilters
End Function

' 返回当前是否只是一个字面量列
Public Function IDFFilterCol_isLiteralCol() As Boolean
    IDFFilterCol_isLiteralCol = originCol.isLiteralCol
End Function

' 返回当前是一个聚合计算列
' 这里有两种可能
'   1. 对于 IDFFilterAggCol 接口实现类，是聚合计算列
'   2. 对一个聚合计算列进行计算，计算结果仍然是聚合计算列
Public Function IDFFilterCol_isAggregateCol() As Boolean
    IDFFilterCol_isAggregateCol = True
End Function

' 返回当前是否只使用了一个 Filter 中的列
' 这里有三种可能
'   1. 只使用了一个 Filter 中的列   ---> True
'   2. 使用了多个 Filter 中的列     ---> False
'   3. 字面量列，没有使用任何 Filter 中的列 ---> False
Public Function IDFFilterCol_isUseSingleFilter() As Boolean
    IDFFilterCol_isUseSingleFilter = originCol.isUseSingleFilter
End Function

' 检查当前列使用的 DFFilter 是否和指定的 DFFilter 相同
' 如果是同表多列的组合，则默认返回 True
' 如果是多表多列的组合，则默认返回 False
Public Function IDFFilterCol_isSameFilter(ByRef filter As DFFilter) As Boolean
    IDFFilterCol_isSameFilter = originCol.isSameFilter
End Function

' 对于聚合列来说，只有在参与组合式聚合列的计算时，才会被调用该方法
Public Function IDFFilterCol_unsafeGetActiveRowVal() As Variant
    ' 从数据源中获取活动行对应的数据
    IDFFilterCol_unsafeGetActiveRowVal = dataSource.getData(activeRowIndex)
End Function

' 克隆一个相同的对象
' 字面量计算列 + 真实列不需要克隆，因为这两种无法进行修改
Public Function IDFFilterCol_clone() As IDFFilterCol
    Set IDFFilterCol_clone = Me

    ' 1. 初始化
    Dim result As DFFilterColMax
    Set result = New DFFilterColMax

    result.Init originCol.clone

    ' 2. 填充别名
    result.IDFFilterCol_alias fieldAliasName

    Set IDFFilterCol_clone = result
End Function
' ------------------------------------------------------
' Filter 过滤器语义操作
' ------------------------------------------------------
' ==================================
' 原地操作
' ==================================
' 返回自身
' 为当前 FilterCol 设置别名
' @param name 别名
' @return 返回当前 FilterCol 对象自身，以完成链式调用
Public Function IDFFilterCol_alias(ByRef name As String) As IDFFilterCol
    fieldAliasName = name
    Set IDFFilterCol_alias = Me
End Function


'///////////////////////////////////////////////////////////////////////////////////
' 通用生成/包装方法
'///////////////////////////////////////////////////////////////////////////////////
' ==================================
' 生成基础运算函数列
' ==================================
' 以当前 FilterCol 为基础创建一个加法计算列
'
' @param val 计算参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
' @return 加法计算列
Public Function IDFFilterCol_add(ByRef val As Variant) As IDFFilterCol
    Set IDFFilterCol_add = DFFilterHelper.unsafeCreateAddCol(Me, val)
End Function

' 以当前 FilterCol 为基础创建一个减法计算列
'
' @param val 计算参数
'            可以是基础类型（只对 INT、DECIMAL 类型有效，其他类型抛出异常）、
'            IDFFilterCol类型(和另一个列进行计算)
' @return 减法计算列
Public Function IDFFilterCol_subtract(ByRef val As Variant) As IDFFilterCol
    Set IDFFilterCol_subtract = DFFilterHelper.unsafeCreateSubtractCol(Me, val)
End Function

' 以当前 FilterCol 为基础创建一个乘法计算列
'
' @param val 计算参数
'            可以是基础类型（只对 INT、DECIMAL 类型有效，其他类型抛出异常）、
'            IDFFilterCol类型(和另一个列进行计算)
' @return 乘法计算列
Public Function IDFFilterCol_multiply(ByRef val As Variant) As IDFFilterCol
    Set IDFFilterCol_multiply = DFFilterHelper.unsafeCreateMultiplyCol(Me, val)
End Function

' 以当前 FilterCol 为基础创建一个除法计算列
'
' @param val 计算参数
'            可以是基础类型（只对 INT、DECIMAL 类型有效，其他类型抛出异常）、
'            IDFFilterCol类型(和另一个列进行计算)
' @return 除法计算列
Public Function IDFFilterCol_divide(ByRef val As Variant) As IDFFilterCol
    Set IDFFilterCol_divide = DFFilterHelper.unsafeCreateDivideCol(Me, val)
End Function

' 以当前 FilterCol 为基础创建一个字符串连接计算列
' @param val 计算参数
'            可以是基础类型（必须是字符串）、IDFFilterCol类型(和另一个列进行计算)
' @return 字符串连接计算列
Public Function IDFFilterCol_concat(ByRef val As Variant) As IDFFilterCol
    Set IDFFilterCol_concat = DFFilterHelper.unsafeCreateConcatCol(Me, val)
End Function

' ==================================
' 生成聚合函数列
' ==================================
' 在当前 FilterCol 的基础上生成最小值计算列
'
' @return IDFFilterCol + IDFFilterAggCol 最小值计算列
Public Function IDFFilterCol_min() As IDFFilterCol
    Set IDFFilterCol_min = DFFilterHelper.unsafeCreateMinCol(Me)
End Function

' 在当前 FilterCol 的基础上生成最大值计算列
'
' @return IDFFilterCol + IDFFilterAggCol 最大值计算列
Public Function IDFFilterCol_max() As IDFFilterCol
    Set IDFFilterCol_max = DFFilterHelper.unsafeCreateMaxCol(Me)
End Function

' 在当前 FilterCol 的基础上生成求和计算列
'
' @return IDFFilterCol + IDFFilterAggCol 求和计算列
Public Function IDFFilterCol_sum() As IDFFilterCol
    Set IDFFilterCol_sum = DFFilterHelper.unsafeCreateSumCol(Me)
End Function

' 在当前 FilterCol 的基础上生成求和计算列
'
' @return IDFFilterCol + IDFFilterAggCol 平均值计算列
Public Function IDFFilterCol_agg() As IDFFilterCol
    Set IDFFilterCol_agg = DFFilterHelper.unsafeCreateAggCol(Me)
End Function

' ==================================
' 条件生成器
' ==================================
' = 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol 类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_eq(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_eq = DFFilterHelper.unsafeCreateConditionEq(Me, val)
End Function

' != 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_ne(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_ne = DFFilterHelper.unsafeCreateConditionNe(Me, val)
End Function

' > 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_gt(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_gt = DFFilterHelper.unsafeCreateConditionGt(Me, val)
End Function

' < 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_lt(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_lt = DFFilterHelper.unsafeCreateConditionLt(Me, val)
End Function

' >= 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_ge(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_ge = DFFilterHelper.unsafeCreateConditionGe(Me, val)
End Function

' <= 运算
'
' @param val 比较参数
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_le(ByRef val As Variant) As IDFFilterColCondition
    Set IDFFilterCol_le = DFFilterHelper.unsafeCreateConditionLe(Me, val)
End Function

' in() 运算
'
' @param vs 比较参数数组
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_inVals(ByRef vs As Variant) As IDFFilterColCondition
    Set IDFFilterCol_inVals = DFFilterHelper.unsafeCreateConditionInVals(Me, vs)
End Function

' between 运算
'
' @param left 左值
' @param right 右值
'            可以是基础类型、IDFFilterCol类型(和另一个列进行计算)
'            不能是 IDFFilterAggCol 聚合计算列，如果使用了将会抛出异常
Public Function IDFFilterCol_between(ByRef left As Variant, ByRef right As Variant) As IDFFilterColCondition
    Set IDFFilterCol_between = DFFilterHelper.unsafeCreateConditionBetween(Me, left, right)
End Function
